#include <stdio.h>
#include <pthread.h>
#include "sys_log.h"
#include "server.h"


int serverSocket = 0;


int create_socket(const char *ip,unsigned short int port)
{
    int ret = 0;
	int sockfd = 0;

	struct sockaddr_in addr;
	memset(&addr,0,sizeof(addr));

	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = inet_addr(ip);

	sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if(sockfd == -1)
	{
		perror("socket");
		exit(-1);
	}

	ret = bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr));
	if(ret == -1)
	{
		perror("bind");
		exit(-1);
	}

	return sockfd;
}




void *producer(void *arg)
{
	char buf[100] = {0};
	int len = 0;
	int ret = 0;

	struct message info;
	memset(&info,0,sizeof(struct message));

	struct producer_consumer *pool = (struct producer_consumer *)arg;

	struct sockaddr_in cliaddr;
	memset(&cliaddr,0,sizeof(cliaddr));
	len = sizeof(struct sockaddr);

    while(1)
	{
		LOG_I("waiting recv message\n");

		ret = recvfrom(serverSocket,buf,100,0,(struct sockaddr *)&cliaddr,&len);
		if(ret == -1)
		{
			perror("recvfrom");
			exit(-1);
		}

		memcpy(info.msg,buf,ret);
		info.cliaddr = cliaddr;
		LOG_D("message is %s\n",buf);
		
		sem_wait(&pool->semw);
		pthread_mutex_lock(&pool->mutex);
		push(pool->que,info);
		pthread_mutex_unlock(&pool->mutex);
		sem_post(&pool->semr);
	}

}

void *consumer(void *arg)
{
	struct message info;
	memset(&info,0,sizeof(struct message));

	struct producer_consumer *pool = (struct producer_consumer*)arg;

	while(1)
	{
		sem_wait(&pool->semr);
		pthread_mutex_lock(&pool->mutex);

		info = front(pool->que);
		pop(pool->que);
		pthread_mutex_unlock(&pool->mutex);
		sem_post(&pool->semw);
		
		
	}
}


struct producer_consumer *model_init(int queue_max_length)
{
	struct producer_consumer *pool = malloc(sizeof(struct producer_consumer));
	if(pool == NULL)
	{
		printf("malloc error\n");
		exit(-1);
	}
	memset(pool,0,sizeof(struct producer_consumer));

	pool->que = create_queue();
	sem_init(&pool->semw,0,queue_max_length);
	sem_init(&pool->semr,0,0);
	pthread_mutex_init(&pool->mutex,NULL);

	return pool;

}


void destroy_model(struct producer_consumer *pool)
{

	sem_destroy(&pool->semr);
	sem_destroy(&pool->semw);
	pthread_mutex_destroy(&pool->mutex);

	free(pool);

}
